package com.nengjiang.wsplayer.oksocket;

import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.google.gson.Gson;
import com.nengjiang.wsplayer.App;
import com.nengjiang.wsplayer.Config;
import com.nengjiang.wsplayer.EventListener;
import com.nengjiang.wsplayer.bean.BaseBean;
import com.nengjiang.wsplayer.bean.BaseResponse;
import com.nengjiang.wsplayer.bean.CarmaResponse;
import com.nengjiang.wsplayer.bean.DefaultSendBean;
import com.nengjiang.wsplayer.bean.HeartbeatBean;
import com.nengjiang.wsplayer.bean.HeartbeatRequest;
import com.nengjiang.wsplayer.bean.HeartbeatResponse;
import com.nengjiang.wsplayer.bean.LoginResponse;
import com.nengjiang.wsplayer.bean.PulseRequest;
import com.nengjiang.wsplayer.bean.VideoResponse;
import com.nengjiang.wsplayer.service.HeartbeatService;
import com.xuhao.didi.core.iocore.interfaces.IPulseSendable;
import com.xuhao.didi.core.iocore.interfaces.ISendable;
import com.xuhao.didi.core.pojo.OriginalData;
import com.xuhao.didi.core.protocol.IReaderProtocol;
import com.xuhao.didi.core.utils.SLog;
import com.xuhao.didi.socket.client.impl.client.action.ActionDispatcher;
import com.xuhao.didi.socket.client.sdk.OkSocket;
import com.xuhao.didi.socket.client.sdk.client.ConnectionInfo;
import com.xuhao.didi.socket.client.sdk.client.OkSocketOptions;
import com.xuhao.didi.socket.client.sdk.client.action.SocketActionAdapter;
import com.xuhao.didi.socket.client.sdk.client.connection.IConnectionManager;
import com.xuhao.didi.socket.client.sdk.client.connection.NoneReconnect;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.util.ArrayList;

/**
 * socket的管理类  消息相关都在这里
 */
public class OkManager {

    public static final String TAG = OkManager.class.getName();

    private IConnectionManager mManager;

    ArrayList<EventListener> eventListeners = new ArrayList<>();

    private OkManager() {

    }

    private static class SingletonHolder {
        private static OkManager instance = new OkManager();
    }

    public static OkManager getInstance() {
        return SingletonHolder.instance;
    }

    public void init() {
        if (mManager != null) {
            return;
        }

        OkSocketOptions.setIsDebug(Config.isDebug);
        SLog.setIsDebug(Config.isDebug);

        final Handler handler = new Handler(Looper.getMainLooper());
        ConnectionInfo mInfo = new ConnectionInfo(Config.SOCKET_URL, Config.SOCKET_PORT);
        OkSocketOptions mOkOptions = new OkSocketOptions.Builder()
                .setReconnectionManager(new NoneReconnect())//有默认的重连机制
                .setConnectTimeoutSecond(10)
                .setCallbackThreadModeToken(new OkSocketOptions.ThreadModeToken() {
                    @Override
                    public void handleCallbackEvent(ActionDispatcher.ActionRunnable runnable) {
                        handler.post(runnable);
                    }
                })
                .setReaderProtocol(new IReaderProtocol() {
                    @Override
                    public int getHeaderLength() {
                        //这里4表示四个字节  每条消息的前面都有一个int类型的数，表示后面数据的长度
                        return 4;
                    }

                    @Override
                    public int getBodyLength(byte[] header, ByteOrder byteOrder) {
                        if (header == null || header.length < getHeaderLength()) {
                            return 0;
                        }
                        ByteBuffer bb = ByteBuffer.wrap(header);
                        bb.order(byteOrder);
                        return bb.getInt();
                    }
                })
                .build();
        mManager = OkSocket.open(mInfo).option(mOkOptions);
        mManager.registerReceiver(new MySocketActionAdapter());
    }


    public void connect() {
        if (mManager == null) {
            return;
        }
        if (!mManager.isConnect()) {
            init();
            mManager.connect();
        } else {
            mManager.disconnect();
        }
    }

    public void updateUrl() {
        if (mManager == null) {
            return;
        }
        if(mManager.isConnect()){
            mManager.disconnect();
            mManager = null;
            init();
            mManager.connect();
        }
        if (!mManager.isConnect()) {
            mManager = null;
            init();
            mManager.connect();
        }
    }

    public void sendMessage(String message) {
        Log.e(TAG, "sendMessage ---> " + message);
        DefaultSendBean defaultSendBean = new DefaultSendBean(message);
        if (mManager != null) {
            mManager.send(defaultSendBean);
        }

    }


    static class MySocketActionAdapter extends SocketActionAdapter {
        @Override
        public void onSocketIOThreadShutdown(String action, Exception e) {
            super.onSocketIOThreadShutdown(action, e);
        }

        @Override
        public void onSocketDisconnection(ConnectionInfo info, String action, Exception e) {
            super.onSocketDisconnection(info, action, e);
            Log.e(TAG, "onSocketDisconnection");
        }

        @Override
        public void onSocketConnectionSuccess(ConnectionInfo info, String action) {
            super.onSocketConnectionSuccess(info, action);
            Log.e(TAG, "onSocketConnectionSuccess");
            OkManager.getInstance().connectSuccess();

//            OkManager.getInstance().startPulse(info);
        }


        @Override
        public void onSocketConnectionFailed(ConnectionInfo info, String action, Exception e) {
            super.onSocketConnectionFailed(info, action, e);
        }

        @Override
        public void onSocketReadResponse(ConnectionInfo info, String action, OriginalData data) {
            super.onSocketReadResponse(info, action, data);
            String str = new String(data.getBodyBytes(), Charset.forName("utf-8"));
            OkManager.getInstance().processMessage(info, str);
        }

        @Override
        public void onSocketWriteResponse(ConnectionInfo info, String action, ISendable data) {
            super.onSocketWriteResponse(info, action, data);
        }

        @Override
        public void onPulseSend(ConnectionInfo info, IPulseSendable data) {
            super.onPulseSend(info, data);
        }
    }


    /**
     * 收到心跳包要操作一次 如果不用框架的心跳就不用处理了
     */
    private void pulseFeed() {
        if (mManager != null) {//是否是心跳返回包,需要解析服务器返回的数据才可知道
            //喂狗操作
            mManager.getPulseManager().feed();
        }
    }


    /**
     * 消息处理方法  收到的消息统一在这里处理
     *
     * @param message
     */
    public void processMessage(ConnectionInfo info, String message) {
        Log.e(TAG, "processMessage---》" + message);
        Gson gson = new Gson();
        BaseResponse baseResponse = gson.fromJson(message, BaseResponse.class);
        int msgType = baseResponse.msgType;
        if (msgType == Event.EVENT_LOGIN_RESPONSE) {
            LoginResponse loginResponse = gson.fromJson(message, LoginResponse.class);
            if (eventListeners != null && eventListeners.size() != 0) {
                for (EventListener eventListener : eventListeners) {
                    eventListener.onLoginRes(loginResponse);
                }
            }
        } else if (msgType == Event.EVENT_HEARTBEAT_INTERVAL__RESPONSE) {
            HeartbeatResponse heartbeatResponse = gson.fromJson(message, HeartbeatResponse.class);
            startHeartbeat(info, heartbeatResponse);

        } else if (msgType == Event.EVENT_VIDEO_URL_REQUEST) {
            VideoResponse videoResponse = gson.fromJson(message, VideoResponse.class);
            processVideo(videoResponse);
        } else if (msgType == Event.EVENT_VIDEO_URL_RESPONSE) {
            VideoResponse videoResponse = gson.fromJson(message, VideoResponse.class);
            processVideo(videoResponse);
        } else if (msgType == Event.EVENT_VIDEO_PUSH_URL_RESPONSE) {
            CarmaResponse carmaResponse = gson.fromJson(message, CarmaResponse.class);
            Config.RTSP_PUSH_URL = carmaResponse.data.cameraStreamUrl;
            pushCarma(carmaResponse);
        }
    }

    public void addEventListener(EventListener listener) {
        synchronized (eventListeners) {
            eventListeners.add(listener);
        }
    }

    public void removeEventListener(EventListener listener) {
        synchronized (eventListeners) {
            int size = eventListeners.size();
            for (int i = 0; i < size; i++) {
                if (eventListeners.get(i) == listener) {
                    eventListeners.remove(i);
                    return;
                }
            }
        }
    }

    public void connectSuccess() {
        if (eventListeners != null && eventListeners.size() != 0) {
            for (EventListener eventListener : eventListeners) {
                eventListener.onConnectionSuccess();
            }
        }
    }

    /**
     * 查询心跳间隔
     */
    public void getHeartbeatInterval() {
        if (mManager != null) {
            HeartbeatRequest heartbeatRequest = new HeartbeatRequest(Event.EVENT_HEARTBEAT_INTERVAL_REQUEST);
            HeartbeatRequest.HeartbeatData heartbeatData = new HeartbeatRequest.HeartbeatData(10);
            heartbeatRequest.data = heartbeatData;
            sendMessage(heartbeatRequest.toJson());
        }
    }

    /**
     * 开始心跳
     *
     * @param response
     */
    private void startHeartbeat(ConnectionInfo info, HeartbeatResponse response) {
        if (response == null) {
            return;
        }
        int heartBeatInterval = response.data.heartBeatInterval;
        Intent intent = new Intent(App.getAppContext(), HeartbeatService.class);
        intent.putExtra("interval", heartBeatInterval);
        App.getAppContext().startService(intent);

    }

    /**
     * 设置心跳
     *
     * @param info
     */
    private void setPulseInfo(ConnectionInfo info, int interval) {
        PulseRequest mPulseData = new PulseRequest(Event.EVENT_PULSE_REQUEST);
        //链式编程调用,给心跳管理器设置心跳数据,一个连接只有一个心跳管理器,因此数据只用设置一次,如果断开请再次设置.
        OkSocket.open(info)
                .getPulseManager()
                .setPulseSendable(mPulseData)//只需要设置一次,下一次可以直接调用pulse()
                .pulse();//开始心跳,开始心跳后,心跳管理器会自动进行心跳触发
    }

    public boolean isConnecting() {
        return mManager != null && mManager.isConnect();
    }

    private void processVideo(VideoResponse videoResponse) {
        if (eventListeners != null && eventListeners.size() != 0) {
            for (EventListener eventListener : eventListeners) {
                eventListener.onVideoRes(videoResponse);
            }
        }
    }

    private void pushCarma(CarmaResponse carmaResponse) {
        if (eventListeners != null && eventListeners.size() != 0) {
            for (EventListener eventListener : eventListeners) {
                eventListener.onCarmaRes(carmaResponse);
            }
        }
    }

    /**
     * 心跳一次
     */
    public void heartOnce() {
        HeartbeatBean heartbeatBean = new HeartbeatBean(Event.EVENT_PULSE_REQUEST);
        sendMessage(heartbeatBean.toJson());
    }


}
